/*     */ package com.zimbra.cs.session;
/*     */ 
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.Element;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.Pair;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxManager;
/*     */ import com.zimbra.cs.redolog.CommitId;
/*     */ import com.zimbra.cs.redolog.RedoLogManager;
/*     */ import com.zimbra.cs.redolog.RedoLogProvider;
/*     */ import java.io.IOException;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collections;
/*     */ import java.util.EnumSet;
/*     */ import java.util.HashSet;
/*     */ import java.util.LinkedList;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Set;
/*     */ import java.util.concurrent.ConcurrentHashMap;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class AllAccountsWaitSet
/*     */   extends WaitSetBase
/*     */ {
/*  46 */   private static Map<AllAccountsWaitSet, String> sAllAccountsWaitSets = new ConcurrentHashMap();
/*  47 */   private static volatile Set<MailItem.Type> interestTypes = EnumSet.noneOf(MailItem.Type.class);
/*     */   private List<Pair<String, String>> mBufferedCommits;
/*     */   private String mCbSeqNo;
/*     */   
/*     */   public static final void mailboxChangeCommitted(String commitIdStr, String accountId, Set<MailItem.Type> changedTypes) {
/*  52 */     if (!Collections.disjoint(changedTypes, interestTypes)) {
/*  53 */       for (AllAccountsWaitSet ws : sAllAccountsWaitSets.keySet()) {
/*  54 */         ws.onMailboxChangeCommitted(commitIdStr, accountId, changedTypes);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public static final boolean isCallbackNecessary(Set<MailItem.Type> types) {
/*  60 */     return !Collections.disjoint(types, interestTypes);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   static AllAccountsWaitSet create(String ownerAccountId, String id, Set<MailItem.Type> defaultInterest)
/*     */   {
/*  67 */     return new AllAccountsWaitSet(ownerAccountId, id, defaultInterest, false);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   static AllAccountsWaitSet createWithSeqNo(String ownerAccountId, String id, Set<MailItem.Type> defaultInterest, String lastKnownSeqNo)
/*     */     throws ServiceException
/*     */   {
/*  76 */     AllAccountsWaitSet ws = new AllAccountsWaitSet(ownerAccountId, id, defaultInterest, true);
/*  77 */     boolean success = false;
/*     */     try
/*     */     {
/*  80 */       ws.syncToCommitId(lastKnownSeqNo);
/*  81 */       success = true;
/*     */     } catch (IOException e) {
/*  83 */       throw ServiceException.FAILURE("Caught IOException when syncing waitset to specified commit ID", e);
/*     */     } finally {
/*  85 */       if (!success) {
/*  86 */         ws.destroy();
/*  87 */         ws = null;
/*     */       }
/*     */     }
/*  90 */     return ws;
/*     */   }
/*     */   
/*     */ 
/*     */   private AllAccountsWaitSet(String ownerAccountId, String id, Set<MailItem.Type> defaultInterest, boolean bufferCommitsAtCreate)
/*     */   {
/*  96 */     super(ownerAccountId, id, defaultInterest);
/*  97 */     this.mCurrentSeqNo = "0";
/*  98 */     this.mCbSeqNo = "0";
/*  99 */     if (bufferCommitsAtCreate) {
/* 100 */       this.mBufferedCommits = new LinkedList();
/*     */     } else {
/* 102 */       this.mBufferedCommits = null;
/*     */     }
/*     */     
/*     */ 
/* 106 */     synchronized (sAllAccountsWaitSets) {
/* 107 */       sAllAccountsWaitSets.put(this, "");
/* 108 */       if (ZimbraLog.session.isDebugEnabled()) {
/* 109 */         ZimbraLog.session.debug("added: sAllAccountsWaitSets.size() = " + sAllAccountsWaitSets.size());
/*     */       }
/*     */       
/*     */ 
/* 113 */       Set<MailItem.Type> types = EnumSet.noneOf(MailItem.Type.class);
/* 114 */       for (AllAccountsWaitSet ws : sAllAccountsWaitSets.keySet()) {
/* 115 */         types.addAll(ws.getDefaultInterest());
/*     */       }
/* 117 */       interestTypes = types;
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   public List<WaitSetError> removeAccounts(List<String> removeAccounts)
/*     */   {
/* 124 */     return new ArrayList();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public synchronized List<WaitSetError> doWait(WaitSetCallback cb, String lastKnownSeqNo, List<WaitSetAccount> addAccounts, List<WaitSetAccount> updateAccounts)
/*     */     throws ServiceException
/*     */   {
/* 132 */     cancelExistingCB();
/*     */     
/*     */ 
/* 135 */     this.mCb = cb;
/* 136 */     this.mCbSeqNo = lastKnownSeqNo;
/* 137 */     trySendData();
/*     */     
/* 139 */     return new ArrayList();
/*     */   }
/*     */   
/*     */   private synchronized void onMailboxChangeCommitted(String commitIdStr, String accountId, Set<MailItem.Type> changedTypes)
/*     */   {
/* 144 */     if (!Collections.disjoint(changedTypes, this.defaultInterest)) {
/* 145 */       if (this.mBufferedCommits != null) {
/* 146 */         this.mBufferedCommits.add(new Pair(accountId, commitIdStr));
/*     */       } else {
/* 148 */         this.mNextSeqNo = commitIdStr;
/* 149 */         this.mCurrentSignalledSessions.add(accountId);
/* 150 */         trySendData();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   private String mCurrentSeqNo;
/*     */   
/*     */   private String mNextSeqNo;
/*     */   
/*     */   private void syncToCommitId(String commitIdStr)
/*     */     throws ServiceException, IOException
/*     */   {
/* 163 */     assert (this.mBufferedCommits != null);
/* 164 */     assert (!Thread.holdsLock(this));
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 169 */     RedoLogManager rmgr = RedoLogProvider.getInstance().getRedoLogManager();
/*     */     
/* 171 */     CommitId cid = CommitId.decodeFromString(commitIdStr);
/*     */     
/* 173 */     Pair<Set<Integer>, CommitId> changes = rmgr.getChangedMailboxesSince(cid);
/* 174 */     if (changes == null) {
/* 175 */       throw ServiceException.FAILURE("Unable to sync to commit id " + commitIdStr, null);
/*     */     }
/*     */     
/* 178 */     Set<Integer> mailboxes = (Set)changes.getFirst();
/*     */     
/* 180 */     for (Integer id : mailboxes) {
/*     */       try {
/* 182 */         Mailbox mbox = MailboxManager.getInstance().getMailboxById(id.intValue());
/* 183 */         if (mbox != null) {
/* 184 */           String accountId = mbox.getAccountId();
/* 185 */           synchronized (this) {
/* 186 */             this.mCurrentSignalledSessions.add(accountId);
/*     */           }
/*     */         }
/*     */       } catch (ServiceException e) {
/* 190 */         ZimbraLog.session.warn("AllAccountsWaitSet skipping notification of mailbox id %d because we could not fetch it", id, e);
/*     */       }
/*     */     }
/*     */     
/*     */ 
/* 195 */     this.mNextSeqNo = ((CommitId)changes.getSecond()).encodeToString();
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 201 */     synchronized (this) {
/* 202 */       for (Pair<String, String> p : this.mBufferedCommits) {
/* 203 */         this.mCurrentSignalledSessions.add(p.getFirst());
/* 204 */         this.mNextSeqNo = ((String)p.getSecond());
/*     */       }
/*     */       
/*     */ 
/* 208 */       this.mBufferedCommits = null;
/*     */       
/* 210 */       if (this.mCurrentSignalledSessions.size() > 0) {
/* 211 */         trySendData();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   protected boolean cbSeqIsCurrent()
/*     */   {
/* 218 */     return this.mCurrentSeqNo.equals(this.mCbSeqNo);
/*     */   }
/*     */   
/*     */ 
/*     */   protected String toNextSeqNo()
/*     */   {
/* 224 */     this.mCurrentSeqNo = this.mNextSeqNo;
/* 225 */     assert (this.mCurrentSeqNo != null);
/* 226 */     return this.mCurrentSeqNo;
/*     */   }
/*     */   
/*     */   int countSessions()
/*     */   {
/* 231 */     return 1;
/*     */   }
/*     */   
/*     */   Map<String, WaitSetAccount> destroy()
/*     */   {
/* 236 */     synchronized (sAllAccountsWaitSets) {
/* 237 */       sAllAccountsWaitSets.remove(this);
/* 238 */       if (ZimbraLog.session.isDebugEnabled()) {
/* 239 */         ZimbraLog.session.debug("removed: sAllAccountsWaitSets.size() = " + sAllAccountsWaitSets.size());
/*     */       }
/*     */       
/*     */ 
/* 243 */       Set<MailItem.Type> types = EnumSet.noneOf(MailItem.Type.class);
/* 244 */       for (AllAccountsWaitSet ws : sAllAccountsWaitSets.keySet()) {
/* 245 */         types.addAll(ws.getDefaultInterest());
/*     */       }
/* 247 */       interestTypes = types;
/*     */     }
/* 249 */     return null;
/*     */   }
/*     */   
/*     */   public synchronized void handleQuery(Element response)
/*     */   {
/* 254 */     super.handleQuery(response);
/*     */     
/* 256 */     response.addAttribute("cbSeqNo", this.mCbSeqNo);
/* 257 */     response.addAttribute("currentSeqNo", this.mCurrentSeqNo);
/* 258 */     response.addAttribute("nextSeqNo", this.mNextSeqNo);
/*     */     Element buffElt;
/* 260 */     if (this.mBufferedCommits != null) {
/* 261 */       buffElt = response.addElement("buffered");
/* 262 */       for (Pair<String, String> p : this.mBufferedCommits) {
/* 263 */         Element e = buffElt.addElement("commit");
/* 264 */         e.addAttribute("aid", (String)p.getFirst());
/* 265 */         e.addAttribute("cid", (String)p.getSecond());
/*     */       }
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/session/AllAccountsWaitSet.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */